package com.mrd.gtimp.business.action;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.mrd.constant.MsgConstants;
import com.mrd.constant.RoleConstants;
import com.mrd.constant.SystemConstants;
import com.mrd.exception.QueryException;
import com.mrd.framework.config.web.json.Result;
import com.mrd.framework.config.web.json.annotation.JField;
import com.mrd.framework.config.web.json.annotation.Json;
import com.mrd.framework.ui.Jqgrid;
import com.mrd.framework.ui.filter.SearchRule;
import com.mrd.framework.ui.filter.SearchRuleOption;
import com.mrd.framework.utils.HttpUtils;
import com.mrd.gtimp.base.entity.User;
import com.mrd.gtimp.business.entity.Attachment;
import com.mrd.gtimp.business.entity.BaseAttachment;
import com.mrd.gtimp.business.entity.Declaration;
import com.mrd.gtimp.business.entity.DeclarationAttachment;
import com.mrd.gtimp.business.entity.DiDanAttachment;
import com.mrd.gtimp.business.entity.RegisteredCompany;
import com.mrd.gtimp.business.entity.RegisteredCompanyAttachment;
import com.mrd.gtimp.business.service.AttachmentBiz;
import com.mrd.gtimp.business.service.BaseAttachmentBiz;
import com.mrd.gtimp.business.service.DeclarationAttachmentBiz;
import com.mrd.gtimp.business.service.DeclarationBiz;
import com.mrd.gtimp.business.service.DiDanAttachmentBiz;
import com.mrd.gtimp.business.service.RegisteredCompanyAttachmentBiz;
import com.mrd.gtimp.business.service.RegisteredCompanyBiz;
import com.mrd.gtimpframe.entity.TBizDeclaReleaseAttachment;
import com.mrd.gtimpframe.repository.TBizDeclaReleaseAttachmentMapper;
import com.mrd.util.JqgridFilterUtils;
import com.mrd.util.LoginUtil;
import com.mrd.util.date.DateUtil;

import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.apache.log4j.Logger;
import org.apache.tools.zip.ZipEntry;
import org.apache.tools.zip.ZipOutputStream;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import static com.mrd.util.AdminUtil.checkRight;

/**
 * <p>
 * application name: gtimp
 * <p>
 * copyright: Copyright@2012 明睿达科技有限公司
 */

/**
 * @author luob
 */

@Controller
@RequestMapping("/business")
public class AttachmentAction {
  private static final long serialVersionUID = 1L;
  /**
   * 日志
   */
  private static final Logger logger = Logger.getLogger(AttachmentAction.class);

  @Value("${file.path}")
  private String fileDir;
  @Value("${file.pay}")
  private String payDir;
  @Value("${file.register}")
  private String registerDir;
  @Value("${file.didan}")
  private String didanDir;
  @Value("${file.offer}")
  private String offerDir;
  @Value("${file.declaration}")
  private String declarationDir;
  @Resource
  private AttachmentBiz attachmentBiz;

  /**
   * 压缩文件临时目录
   */
  private static final String ZIP_TEMP_PATH =
      "WEB-INF" + File.separator + "ZIP_TEMP_PATH" + File.separator;
  @Resource
  private BaseAttachmentBiz<BaseAttachment> baseAttachmentBiz;
  @Resource
  private TBizDeclaReleaseAttachmentMapper tBizDeclaReleaseAttachmentMapper;

  /**
   * 附件查看下载主页
   */
  @RequestMapping("/queryMain")
  public String queryMain() {
    return "gtimp3/attachment/queryMain";
  }

  /**
   * 附件上传操作主页
   */
  @RequestMapping("/uploadMain")
  public String uploadMain() {
    return "gtimp3/attachment/uploadMain";
  }

  /**
   * 文件上传保存方法，注意，本文件不做数据库保存操作
   */
  private Attachment saveUploadFile(MultipartFile uploadFile, String type) {
    String name = uploadFile.getOriginalFilename();
    String suffix = "";
    if (name.contains(".")) {
      suffix = name.substring(name.lastIndexOf(".") + 1);
    }
    File file = null;
    Date now = null;
    String newFilePathName = null;
    String newFileName = null;
    while (file == null || file.exists()) {
      now = new Date();
      newFileName = DateFormatUtils.format(now, "yyyyMMddHHmmssSSS");
      newFilePathName = String.format("\\%s\\%s\\%s.%s", type,
          DateFormatUtils.format(now, "yyyy\\MM\\dd"), newFileName, suffix);
      String filePath = String.format("%s\\%s", fileDir, newFilePathName);
      file = new File(filePath);
    }
    try (InputStream is = uploadFile.getInputStream()) {
      FileUtils.copyToFile(is, file);
    } catch (IOException e) {
      logger.error("文件上传出错!", e);
      return null;
    }
    Attachment attachment = new Attachment();
    attachment.setId(null);
    attachment.setCtime(now);
    attachment.setName(name);
    attachment.setReplacename(newFileName);
    attachment.setPath(newFilePathName);
    try {
      attachment.setCREATOR(LoginUtil.getLoginUser().getId());
    } catch (Exception e) {
    }
    // attachmentBiz.saveOrupdateEntity(attachment);
    return attachment;
  }

  /**
   * 默认访问入口
   */
  @RequestMapping("/attach-main")
  public String main(Model model) {
    model.addAttribute("id", HttpUtils.getParam("id"));
    return "/gtimp/attachment/main";
  }

  /**
   * 默认新增修改入口
   */
  @RequestMapping("/attach-manage")
  public String manage() {
    return "manage";
  }

  /**
   * 新增或修改信息
   */
  @RequestMapping("/attach-saveOrUpdate")
  @ResponseBody
  public Result saveOrUpdate(Attachment attachment) {
    Result msg;
    if (checkRight(RoleConstants.SUP_CUSTOMER_SAVE)) {
      try {
        if (StringUtils.isEmpty(attachment.getId())) { // 新增操作
          // attachment.setCOM_ID(user.getCompany().getId());
          attachment.setCREATOR(LoginUtil.getLoginUser().getAccount());
          attachment.setCtime(new Date());
          attachment.setId(null);
        } else { // 修改操作
          // attachment.setMODIFIER(user.getAccount());
          // attachment.setMTIME(new Date());
        }
        attachmentBiz.saveOrupdateEntity(attachment);
        msg = Result.newSuccessInstance(MsgConstants.SAVE_SUECCES);
      } catch (Exception e) {
        e.printStackTrace();
        msg = Result.newFailInstance(MsgConstants.SAVE_FAIL);
      }
      return msg;
    }
    return Result.newFailInstance(SystemConstants.ROLE_FAIL);
  }

  /**
   * 编辑信息
   */
  @RequestMapping("/attach-find")
  @ResponseBody
  public Attachment find(String id) {
    if (StringUtils.isEmpty(id)) {
      return null;
    }
    try {
      Attachment attachment = attachmentBiz.findEntityById(id);
      return attachment;
    } catch (QueryException e) {
      e.printStackTrace();
    }
    return null;
  }

  /**
   * 删除信息
   */
  @RequestMapping("/attach-del")
  @ResponseBody
  public Result del() {
    Result msg;
    // if (checkRight(RoleConstants.SUP_CUSTOMER_DEL)) {
    String type = HttpUtils.getParam("type");
    Map<String, String> typeMap = new HashMap<>();
    typeMap.put("reg", "register");
    typeMap.put("declaration", "declaration");
    typeMap.put("didan", "didan");
    typeMap.put("payMent", "pay");
    typeMap.put("offer", "declaOffer");
    try {
      if (LoginUtil.getLoginUser() == null && !"reg".equals(type)) {
        return Result.newFailInstance("非法操作");
      }
      String ids = HttpUtils.getParam("id");
      String[] idArr = ids.split(",");
      attachmentBiz.deleteAttachement(typeMap.get(type), idArr);
      msg = Result.newSuccessInstance(MsgConstants.SAVE_SUECCES);
      return msg;
    } catch (Exception e) {
      e.printStackTrace();
      msg = Result.newFailInstance(MsgConstants.SAVE_FAIL);
      // }
      return msg;
    }
    // return Result.newFailInstance(SystemConstants.ROLE_FAIL);
  }

  /**
   * 查询
   */
  @RequestMapping("/attach-findList")
  @ResponseBody
  @Json({@JField("id"), @JField("name"), @JField("ctime")})
  public Page<Attachment> findList(@RequestParam(required = false) String id, Jqgrid jqgrid) {
    // String comId = LoginUtil.getLoginUser().getCompany().getId();// get from user
    if (StringUtils.isEmpty(id)) {
      return null;
    }
    try {
      jqgrid.addRule(new SearchRule("id", SearchRuleOption.eq, id));
      // SearchRule rule = new SearchRule("COM_ID", SearchRuleOption.eq, comId);
      // jqgrid.addRule(rule);
      Page<Attachment> attachments = attachmentBiz.findByJqgrid(jqgrid);
      return attachments;

    } catch (Exception e) {
      e.printStackTrace();
    }
    return null;
  }

  /**
   * 取消上传的文件
   */
  @RequestMapping("/attach-cancleFile")
  @ResponseBody
  public Result cancleFile(String fileId) {
    Result msg = null;
    try {
      if (StringUtils.isNotEmpty(fileId)) {
        String businessType = HttpUtils.getParam("businessType");
        boolean rs = attachmentBiz.cancleUploadFile(fileId, businessType);
        if (rs) {
          msg = Result.newSuccessInstance(MsgConstants.FILE_CANCLE_SUCCESS);
        } else {
          msg = Result.newFailInstance(MsgConstants.FILE_CANCLE_ERROR);
        }
      } else {
        msg = Result.newFailInstance(MsgConstants.FILE_CANCLE_ERROR);
      }
    } catch (Exception e) {
      e.printStackTrace();
    }
    return msg;
  }

  @Resource
  public void setAttachmentBiz(AttachmentBiz attachmentBiz) {
    this.attachmentBiz = attachmentBiz;
  }

  // ======================================GTIMP 3.0======================

  /**
   * 查询
   */
  @RequestMapping("/attach/findListByBillNo")
  @ResponseBody
  @Json({@JField("id"), @JField("name"), @JField("ctime")})
  public Object findListByBillNo(@RequestParam(required = true) String bill_no, String type,
      Jqgrid jqgrid) {
    switch (type) {
      case "reg":// 注册资料
        return findRegListByBillNo(bill_no, jqgrid);
      case "declaration":// 报关单
        return findDeclarationListByBillNo(bill_no, jqgrid);
      case "didan":// 报价
        return findDidanListByBillNo(bill_no, jqgrid);
      case "offer":
        return findOfferListByBillNo(bill_no, jqgrid);
      case "payMent":
        return findOfferListByBillNo(bill_no, jqgrid);
      case "secondSup":
        return findSecondSupListByBillNo(bill_no, jqgrid);
      default:// 其他
        return findDidanListByBillNo(bill_no, jqgrid);
    }
  }

  /**
   * 底单附件查询
   */
  public Page<DiDanAttachment> findDidanListByBillNo(@RequestParam(required = true) String bill_no,
      Jqgrid jqgrid) {
    try {
      jqgrid.addRule(new SearchRule("bill_no", SearchRuleOption.eq, bill_no));
      Page<DiDanAttachment> attachments = diDanAttachmentBiz.findByJqgrid(jqgrid);
      return attachments;
    } catch (Exception e) {
      e.printStackTrace();
    }
    return null;
  }

  /**
   * 底单附件查询
   */
  public Page<Attachment> findOfferListByBillNo(@RequestParam(required = true) String bill_no,
      Jqgrid jqgrid) {
    try {
      jqgrid.addRule(new SearchRule("bill_no", SearchRuleOption.eq, bill_no));
      Page<Attachment> attachments = attachmentBiz.findByJqgrid(jqgrid);
      return attachments;
    } catch (Exception e) {
      e.printStackTrace();
    }
    return null;
  }

  /**
   * 注册附件查询
   */
  public Page<RegisteredCompanyAttachment> findRegListByBillNo(
      @RequestParam(required = true) String bill_no, Jqgrid jqgrid) {
    try {
      jqgrid.addRule(new SearchRule("bill_no", SearchRuleOption.eq, bill_no));
      Page<RegisteredCompanyAttachment> attachments =
          registeredCompanyAttachmentBiz.findByJqgrid(jqgrid);
      return attachments;
    } catch (Exception e) {
      e.printStackTrace();
    }
    return null;
  }

  /**
   * 报关单附件查询
   */
  public Page<DeclarationAttachment> findDeclarationListByBillNo(
      @RequestParam(required = true) String bill_no, Jqgrid jqgrid) {
    try {
      jqgrid.addRule(new SearchRule("bill_no", SearchRuleOption.eq, bill_no));
      Page<DeclarationAttachment> attachments = declarationAttachmentBiz.findByJqgrid(jqgrid);
      return attachments;
    } catch (Exception e) {
      e.printStackTrace();
    }
    return null;
  }

  @Resource
  private DiDanAttachmentBiz diDanAttachmentBiz;
  @Resource
  private DeclarationBiz declarationBiz;

  @Resource
  private RegisteredCompanyAttachmentBiz registeredCompanyAttachmentBiz;
  @Resource
  private DeclarationAttachmentBiz declarationAttachmentBiz;
  @Resource
  private RegisteredCompanyBiz registeredCompanyBiz;

  /**
   * 文件上传操作
   */
  @RequestMapping(value = "/attach/doUpload", method = RequestMethod.POST)
  @ResponseBody
  public Result doUpload(String bill_no, String type, @RequestParam MultipartFile attach,
      HttpServletRequest request) {
    if ("declare".equals(type)) {
      type = "declaration";
    }
    switch (type) {
      case "reg":
        return doRegUpload(bill_no, attach, request);
      case "declaration":
        return doDeclarationUpload(bill_no, attach, request);
      case "offer":
        return doOfferUpload(bill_no, attach, request);
      case "payMent":
        return doPaymentTransferUpload(bill_no, attach);
      case "secondSup":
        return doSecondSupUpload(bill_no, attach, request);
      default:
        return doDidanUpload(bill_no, attach, request);
    }
  }

  /**
   * 报关底单文件上传操作
   */
  public Result doDidanUpload(String bill_no, @RequestParam MultipartFile attach,
      HttpServletRequest request) {
    if (StringUtils.isNoneEmpty(bill_no)) {
      Declaration d = null;
      try {
        d = declarationBiz.findEntityById(bill_no);
      } catch (QueryException e) {
      }
      if (d != null) {
        try {
          Attachment saveFileResult = saveUploadFile(attach, didanDir);
          if (saveFileResult != null) {
            DiDanAttachment attachment = new DiDanAttachment();
            attacheCover(saveFileResult, attachment);
            attachment.setBill_no(bill_no);
            attachment.setDeclaration(d);
            diDanAttachmentBiz.saveOrupdateEntity(attachment);
          } else {
            return Result.newFailInstance("文件上传失败！");
          }
        } catch (Exception e) {
          String msg = "操作失败.";
          logger.error(String.format("%s", msg), e);
          return Result.newFailInstance(msg);
        }
      } else {
        String msg = "操作失败. 不存在的报关单信息.";
        logger.error(String.format("%s%s", msg, bill_no));
        return Result.newFailInstance(msg);
      }
    }
    return Result.newSuccessInstance("提交成功.");
  }

  /**
   * 报关单文件上传操作
   */
  public Result doDeclarationUpload(String bill_no, @RequestParam MultipartFile attach,
      HttpServletRequest request) {
    Result result = Result.newFailInstance("上传成功");
    if (StringUtils.isNoneEmpty(bill_no)) {
      Declaration d = null;
      try {
        d = declarationBiz.findEntityById(bill_no);
      } catch (QueryException e) {
        logger.error("查找报关单失败!", e);
      }
      try {
        Attachment saveFileResult = saveUploadFile(attach, declarationDir);
        if (saveFileResult != null) {
          DeclarationAttachment attachment = new DeclarationAttachment();
          attacheCover(saveFileResult, attachment);
          attachment.setBill_no(bill_no);
          if (d != null) {
            attachment.setDeclaration(d);
          }
          declarationAttachmentBiz.saveOrupdateEntity(attachment);
          result.setData(new String[] {attachment.getId(), attachment.getName()});
        } else {
          return Result.newFailInstance("文件上传失败！");
        }
      } catch (Exception e) {
        String msg = "操作失败.";
        logger.error(String.format("%s", msg), e);
        return Result.newFailInstance(msg);
      }
    }
    return result;
  }

  /**
   * 注册文件上传操作
   */
  public Result doRegUpload(String bill_no, @RequestParam MultipartFile attach,
      HttpServletRequest request) {
    if (StringUtils.isNoneEmpty(bill_no)) {
      RegisteredCompany d = null;
      try {
        d = registeredCompanyBiz.findEntityById(bill_no);
      } catch (QueryException e) {
        logger.error("查找注册公司资料失败!", e);
      }
      try {
        Attachment saveFileResult = saveUploadFile(attach, registerDir);
        if (saveFileResult != null) {
          RegisteredCompanyAttachment attachment = new RegisteredCompanyAttachment();
          attacheCover(saveFileResult, attachment);
          attachment.setBill_no(bill_no);
          if (d != null) {
            attachment.setRegisteredCompany(d);
          }
          registeredCompanyAttachmentBiz.saveOrupdateEntity(attachment);
        } else {
          return Result.newFailInstance("文件上传失败！");
        }
      } catch (Exception e) {
        String msg = "操作失败.";
        logger.error(String.format("%s", msg), e);
        return Result.newFailInstance(msg);
      }
    }
    return Result.newSuccessInstance("提交成功.");
  }

  /**
   * 报价上传操作
   */
  private Result doOfferUpload(String bill_no, @RequestParam MultipartFile attach,
      HttpServletRequest request) {
    if (StringUtils.isNoneEmpty(bill_no)) {
      try {
        Attachment saveFileResult = saveUploadFile(attach, offerDir);
        if (saveFileResult != null) {
          saveFileResult.setBill_no(bill_no);
          attachmentBiz.saveOrupdateEntity(saveFileResult);
        } else {
          return Result.newFailInstance("文件上传失败！");
        }
      } catch (Exception e) {
        String msg = "操作失败.";
        logger.error(String.format("%s", msg), e);
        e.printStackTrace();
        return Result.newFailInstance(msg);
      }
    }
    return Result.newSuccessInstance("提交成功.");
  }

  /**
   * 报价上传操作
   */
  private Result doPaymentTransferUpload(String bill_no, @RequestParam MultipartFile attach) {
    if (StringUtils.isNoneEmpty(bill_no)) {
      try {
        Attachment saveFileResult = saveUploadFile(attach, payDir);
        if (saveFileResult != null) {
          saveFileResult.setBill_no(bill_no);
          attachmentBiz.saveOrupdateEntity(saveFileResult);
        } else {
          return Result.newFailInstance("水单上传失败！");
        }
      } catch (Exception e) {
        String msg = "操作失败.";
        logger.error(String.format("%s", msg), e);
        return Result.newFailInstance(msg);
      }
    }
    return Result.newSuccessInstance("提交成功.");
  }

  /**
   * 下载页面
   */
  @RequestMapping("/downloadPage")
  public String downloadPage(Model model, String attaId, String type, Jqgrid jqgrid) {
    if (StringUtils.isEmpty(type)) {
      type = "didan";/* 默认底单 */
    }
    if ("payMent".equals(type) || "declaOffer".equals(type) || "offer".equals(type)) {
      List<Attachment> attachments = attachmentBiz.findByIds(new String[] {attaId});
      model.addAttribute("attachmentList", attachments);
    } else if ("declaration".equals(type) || "didan".equals(type) || "register".equals(type)
        || "reg".equals(type)) {
      List<BaseAttachment> attachments = baseAttachmentBiz.findByIds(new String[] {attaId});
      model.addAttribute("attachmentList", attachments);
    }
    return "gtimp3/attachment/downloadPage";
  }

  @RequestMapping("/didanDownload")
  @ResponseBody
  public void didanDownload(HttpServletRequest request, HttpServletResponse response, String id) {
    try {
      if (StringUtils.isEmpty(id)) {
        throw new Exception("底单下载失败，id为空！");
      }

      DiDanAttachment attachment = diDanAttachmentBiz.findEntityById(id);
      String filePath = attachment.getPath();
      if (StringUtils.isNotEmpty(filePath) && filePath.startsWith("\\")) {
        filePath = filePath.substring(1, filePath.length());
      }
      String basePath = request.getServletContext().getRealPath("/");
      String downloadFilePath = basePath + filePath;
      this.download(request, response, downloadFilePath, attachment.getName());
    } catch (Exception e) {
      logger.error("AttachmentAction.didanDownload.[id=" + id + "]底单下载失败！");
      e.printStackTrace();
    }
  }

  @RequestMapping("/didanDownloadAll")
  @ResponseBody
  public void didanDownloadAll(HttpServletRequest request, HttpServletResponse response,
      String declarationId, Jqgrid jqgrid) throws Exception {
    if (StringUtils.isEmpty(declarationId)) {
      throw new Exception("底单下载失败，declarationId为空！");
    }
    jqgrid.addRule(new SearchRule("bill_no", SearchRuleOption.eq, declarationId));
    Page<DiDanAttachment> diDanAttachmentPage = diDanAttachmentBiz.findByJqgrid(jqgrid);
    if (diDanAttachmentPage != null) {
      List<DiDanAttachment> diDanAttachmentList = diDanAttachmentPage.getContent();
      if (diDanAttachmentList != null && diDanAttachmentList.size() > 0) {
        List<File> fileList = new ArrayList<>();
        String basePath = request.getServletContext().getRealPath("/");
        fileList.addAll(diDanAttachmentList.stream()
            .map(attachment -> new File(basePath + attachment.getPath()))
            .collect(Collectors.toList()));
        if (fileList.size() > 0) {
          File outputFile =
              new File(basePath + ZIP_TEMP_PATH + System.currentTimeMillis() + ".zip");
          filesToZip(fileList, outputFile);
          this.download(request, response, outputFile.getPath(), "底单打包下载文件.zip");
          if (outputFile.exists()) {
            outputFile.delete();
          }
        }
      }
    }
  }

  /**
   * 设置让浏览器弹出下载对话框的Header. 根据浏览器的不同设置不同的编码格式 防止中文乱码
   * 
   * @param fileName 下载后的文件名.
   */
  private void download(HttpServletRequest request, HttpServletResponse response,
      String downloadFilePath, String fileName) {
    File downFiles = new File(downloadFilePath);
    if (!downFiles.exists()) {
      return;
    }
    if (!fileName.contains(".") && downloadFilePath.contains(".")) {
      fileName += downloadFilePath.substring(downloadFilePath.lastIndexOf("."));
    }
    try (InputStream fis = new FileInputStream(downFiles);
        BufferedInputStream bis = new BufferedInputStream(fis);
        OutputStream fos = response.getOutputStream();
        BufferedOutputStream bos = new BufferedOutputStream(fos)) {
      // 中文文件名支持
      String encodedFileName;
      String agent = request.getHeader("USER-AGENT");
      if (agent != null && agent.contains("MSIE")) {// IE
        encodedFileName = java.net.URLEncoder.encode(fileName, "UTF-8");
      } else if (agent != null && agent.contains("Mozilla")) {
        encodedFileName = new String(fileName.getBytes("UTF-8"), "iso-8859-1");
      } else {
        encodedFileName = java.net.URLEncoder.encode(fileName, "UTF-8");
      }
      response.setHeader("Content-Disposition", "attachment; filename=\"" + encodedFileName + "\"");
      response.setHeader("Content-Length", "" + downFiles.length());
      int byteRead;
      byte[] buffer = new byte[2048];
      while ((byteRead = bis.read(buffer, 0, 2048)) != -1) {
        bos.write(buffer, 0, byteRead);
      }
      bos.flush();
    } catch (Exception e) {
      e.printStackTrace();
    }
  }

  /**
   * 业务文件下载，包括底单、注册资料、报关单、支付材料， 一个业务下有多个符合类型要求的附件时，打包之后再下载
   * 
   * @param atype 文件类型
   * @param bid 业务ID， 可能是待审核注册信息ID、或报关单ID、或者支付流水ID
   */
  @RequestMapping("/downloadBizAttachment")
  public void downloadBizAttachment(HttpServletRequest request, HttpServletResponse response,
      String atype, String bid) {
    List<Object> attas = attachmentBiz.queryBaseAttachmentOrAttachment(atype, bid);
    String basePath = request.getServletContext().getRealPath("/");
    if ("register".equals(atype) || "declaration".equals(atype) || "didan".equals(atype)
        || "declaOffer".equals(atype)) {
      Map<String, String> zipNameMap = new HashMap<>();
      zipNameMap.put("register", "注册附件打包下载文件.zip");
      zipNameMap.put("declaration", "报关资料打包下载文件.zip");
      zipNameMap.put("didan", "底单打包下载文件.zip");
      List<BaseAttachment> baseAttachments =
          attas.stream().map(atta -> (BaseAttachment) atta).collect(Collectors.toList());
      if (baseAttachments.size() > 1) {// 超过一个文件，需要打包
        List<File> fileList = new ArrayList<>();
        fileList.addAll(
            baseAttachments.stream().map(attachment -> new File(basePath + attachment.getPath()))
                .collect(Collectors.toList()));
        if (fileList.size() > 0) {
          String zipFileName = zipNameMap.get(atype);
          File outputFile =
              new File(basePath + ZIP_TEMP_PATH + System.currentTimeMillis() + ".zip");
          filesToZip(fileList, outputFile);
          this.download(request, response, outputFile.getPath(), zipFileName);
          if (outputFile.exists()) {
            outputFile.delete();
          }
        }
      } else if (baseAttachments.size() == 1) {
        BaseAttachment baseAttachment = baseAttachments.get(0);
        this.download(request, response, basePath + baseAttachment.getPath(),
            baseAttachment.getName());
      }
    } else if ("pay".equals(atype)) { // 支付水单
      List<Attachment> attachments =
          attas.stream().map(atta -> (Attachment) atta).collect(Collectors.toList());
      if (attachments.size() > 1) {// 超过一个文件，需要打包
        List<File> fileList = new ArrayList<>();
        fileList.addAll(
            attachments.stream().map(attachment -> new File(basePath + attachment.getPath()))
                .collect(Collectors.toList()));
        if (fileList.size() > 0) {
          File outputFile =
              new File(basePath + ZIP_TEMP_PATH + System.currentTimeMillis() + ".zip");
          filesToZip(fileList, outputFile);
          this.download(request, response, outputFile.getPath(), "水单打包下载文件.zip");
          if (outputFile.exists()) {
            outputFile.delete();
          }
        }
      } else if (attachments.size() == 1) {
        Attachment attachment = attachments.get(0);
        this.download(request, response, basePath + attachment.getPath(), attachment.getName());
      }
    }
  }

  /**
   * 业务文件下载，包括底单、注册资料、报关单、支付材料、报价资料
   * 
   * @param atype 文件类型
   * @param aid 附件ID
   */
  @RequestMapping("/downloadSingleBizAttachment")
  public void downloadSingleBizAttachment(HttpServletRequest request, HttpServletResponse response,
      String atype, String aid) {
    String fatype = "payMent".equals(atype) ? "pay" : atype;// fix Bug#1174
    fatype = "offer".equals(atype) ? "declaOffer" : atype;// fix Bug#1204
    Object atta = attachmentBiz.querySingleBaseAttachmentOrAttachment(fatype, aid);
    if ("reg".equals(atype) || "register".equals(atype) || "declaration".equals(atype)
        || "didan".equals(atype)) {
      BaseAttachment baseAttachment = (BaseAttachment) atta;
      this.download(request, response, fileDir + baseAttachment.getPath(),
          baseAttachment.getName());
    } else if ("pay".equals(atype) || "payMent".equals(atype) || "declaOffer".equals(atype)
        || "offer".equals(atype)) { // 支付水单
      Attachment attachment = (Attachment) atta;
      this.download(request, response, fileDir + attachment.getPath(), attachment.getName());
    }
  }

  /**
   * 压缩多个文件
   */
  public static void filesToZip(List<File> files, File outputFile) {
    if (files != null && files.size() > 0) {
      File parentFile = outputFile.getParentFile();
      if (!parentFile.exists()) {
        parentFile.mkdirs();
      }
      for (File file : files) {
        fileToZip(file, outputFile);
      }
    }
  }

  /**
   * 压缩单个文件或文件夹
   */
  public static void fileToZip(File inputFile, File outputFile) {
    if (inputFile.exists()) {
      if (inputFile.isFile()) {
        InputStream inputStream = null;
        ZipOutputStream outputStream = null;
        try {
          outputStream = new ZipOutputStream(new FileOutputStream(outputFile));
          inputStream = new BufferedInputStream(new FileInputStream(inputFile), 512);
          ZipEntry zipEntry = new ZipEntry(inputFile.getName());
          outputStream.putNextEntry(zipEntry);
          int nNumber;
          byte[] buffer = new byte[512];
          while ((nNumber = inputStream.read(buffer)) != -1) {
            outputStream.write(buffer, 0, nNumber);
          }
          outputStream.flush();
        } catch (Exception e) {
          e.printStackTrace();
        } finally {
          try {
            outputStream.close();
            inputStream.close();
          } catch (IOException e) {
            e.printStackTrace();
          }
        }
      } else {
        File[] files = inputFile.listFiles();
        for (File file : files) {
          fileToZip(file, outputFile);
        }
      }
    }
  }

  /**
   * attachment对象转换成BaseAttachment对象
   */
  private BaseAttachment attacheCover(Attachment attachment, BaseAttachment cover) {
    cover.setId(attachment.getId());
    cover.setPath(attachment.getPath());
    cover.setName(attachment.getName());
    cover.setRemark(attachment.getRemark());
    if (StringUtils.isNoneEmpty(attachment.getCREATOR())) {
      User user = new User();
      user.setId(attachment.getCREATOR());
      cover.setCREATOR(user);
    }
    cover.setCtime(attachment.getCtime());
    cover.setReplacename(attachment.getReplacename());
    return cover;
  }

  /**
   * 二级供应商补料
   * 
   * @author han
   * @param bill_no
   * @param attach
   * @return
   */
  private Result doSecondSupUpload(String bill_no, @RequestParam MultipartFile attach,
      HttpServletRequest request) {
    Result result = Result.newFailInstance("上传成功");
    if (StringUtils.isNoneEmpty(bill_no)) {
      Declaration d = null;
      try {
        d = declarationBiz.findEntityById(bill_no);
      } catch (QueryException e) {
        logger.error("查找报关单失败!", e);
      }
      try {
        Attachment saveFileResult = saveUploadFile(attach, declarationDir);
        if (saveFileResult != null) {
          DeclarationAttachment attachment = new DeclarationAttachment();
          // attachmentBiz.saveOrupdateEntity(saveFileResult);
          attacheCover(saveFileResult, attachment);
          attachment.setBill_no(bill_no);
          if (d != null) {
            attachment.setDeclaration(d);
          }
          declarationAttachmentBiz.saveOrupdateEntity(attachment);
          TBizDeclaReleaseAttachment releaseAttachment = new TBizDeclaReleaseAttachment();
          releaseAttachment.setId(attachment.getId());
          String comId = LoginUtil.getLoginUser().getCompany().getId();// 此处为供应商
          releaseAttachment.setCreator(comId);
          releaseAttachment.setCreateTime(
              DateUtil.formatDate(saveFileResult.getCtime(), DateUtil.FORMAT_DATETIME_TYPE));
          releaseAttachment.setDid(bill_no);
          // releaseAttachment.setId(saveFileResult.getId());
          tBizDeclaReleaseAttachmentMapper.insert(releaseAttachment);
          result.setData(new String[] {attachment.getId(), attachment.getName()});
        } else {
          return Result.newFailInstance("文件上传失败！");
        }
      } catch (Exception e) {
        String msg = "操作失败.";
        logger.error(String.format("%s", msg), e);
        return Result.newFailInstance(msg);
      }
    }
    return result;
  }

  /**
   * 通关一体化放行附件下载
   * 
   * @author han
   */
  public Page<com.mrd.gtimpframe.entity.BaseAttachment> findSecondSupListByBillNo(
      @RequestParam(required = true) String bill_no, Jqgrid jqgrid) {
    try {
      jqgrid.addRule(new SearchRule("did", SearchRuleOption.eq, bill_no));
      String sql = JqgridFilterUtils.getSql(jqgrid.getFilters(), Attachment.class, "t.");

      Pageable page = jqgrid.getPage();
      int pageNumber = page.getPageNumber();
      int pageSize = page.getPageSize();
      // 分页
      PageHelper.startPage(pageNumber + 1, pageSize);

      Map<String, Object> map = new HashMap<String, Object>();
      map.put("Sql", sql);
      List<com.mrd.gtimpframe.entity.BaseAttachment> list =
          tBizDeclaReleaseAttachmentMapper.selectBySql(map);
      PageInfo<com.mrd.gtimpframe.entity.BaseAttachment> pi =
          new PageInfo<com.mrd.gtimpframe.entity.BaseAttachment>(list);
      Page<com.mrd.gtimpframe.entity.BaseAttachment> pMap = new PageImpl(list, page, pi.getTotal());
      return pMap;
    } catch (Exception e) {
      e.printStackTrace();
    }
    return null;
  }
}
